home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
windownt
/
mapmem.zip
/
DRIVER
/
MAPMEM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-24
|
14KB
|
527 lines
//
// Simple driver that demonstrates mapping physical memory into
// a user mode process's address space
//
#include "ntddk.h"
#include "..\mapmem.h"
#include "stdarg.h"
//
// The following was not included in the October release of the
// preliminary NT DDK, and is necessary when utilizing the
// ZwMapViewOfSection API.
//
#define SECTION_QUERY 0x0001
#define SECTION_MAP_WRITE 0x0002
#define SECTION_MAP_READ 0x0004
#define SECTION_MAP_EXECUTE 0x0008
#define SECTION_EXTEND_SIZE 0x0010
#define SECTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SECTION_QUERY | \
SECTION_MAP_WRITE | \
SECTION_MAP_READ | \
SECTION_MAP_EXECUTE | \
SECTION_EXTEND_SIZE)
typedef enum _SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT;
#define PAGE_NOACCESS 0x01 // winnt
#define PAGE_READONLY 0x02 // winnt
#define PAGE_READWRITE 0x04 // winnt
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
NTSTATUS
ZwMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PULONG ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect
);
//
// Function prototypes for this module
//
NTSTATUS
MapMemCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
MapMemDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
MapMemMapTheMemory(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PVOID ioBuffer,
IN ULONG inputBufferLength,
IN ULONG outputBufferLength
);
#if DBG
#define MapMemDebugPrint(arg) DbgPrint arg
#else
#define MapMemDebugPrint(arg)
#endif
//
// The code...
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus;
WCHAR deviceNameBuffer[] = L"\\Device\\MapMem";
UNICODE_STRING deviceNameUnicodeString;
MapMemDebugPrint(("MapMem: entering DriverEntry\n"));
RtlInitUnicodeString(&deviceNameUnicodeString,
deviceNameBuffer);
//
// Create the device object
//
ntStatus = IoCreateDevice(
DriverObject,
0,
&deviceNameUnicodeString,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&deviceObject
);
if (NT_SUCCESS(ntStatus))
{
//
// Create dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MapMemCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MapMemDispatch;
}
return ntStatus;
}
NTSTATUS
MapMemCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
//
// No need to do anything.
//
//
// Fill these in before calling IoCompleteRequest.
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
MapMemDebugPrint(("MapMemOpenClose: enter\n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(
Irp,
IO_NO_INCREMENT
);
return STATUS_SUCCESS;
}
NTSTATUS
MapMemDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
//
// Init to default settings- we only expect 1 type of
// IOCTL to roll through here, all others an error.
//
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
//
// Get the pointer to the input/output buffer and it's length
//
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength =
irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY:
Irp->IoStatus.Status = MapMemMapTheMemory (DeviceObject,
ioBuffer,
inputBufferLength,
outputBufferLength
);
if (NT_SUCCESS(Irp->IoStatus.Status))
{
//
// Success! Set the following to sizeof(PVOID) to
// indicate we're passing valid data back.
//
Irp->IoStatus.Information = sizeof(PVOID);
MapMemDebugPrint(("MapMem: memory successfully mapped :)\n"));
}
else
MapMemDebugPrint(("MapMem: memory map failed :(\n"));
break;
default:
MapMemDebugPrint(("MapMem: unknown IRP_MJ_DEVICE_CONTROL\n"));
break;
} // switch (ioControlCode)
break;
}
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
//
// We never have pending operation so always return the status code.
//
return ntStatus;
}
NTSTATUS
MapMemMapTheMemory(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PVOID ioBuffer,
IN ULONG inputBufferLength,
IN ULONG outputBufferLength
)
{
PPHYSICAL_MEMORY_INFO ppmi = (PPHYSICAL_MEMORY_INFO) ioBuffer;
INTERFACE_TYPE interfaceType;
ULONG busNumber;
PHYSICAL_ADDRESS physicalAddress;
ULONG length;
UNICODE_STRING physicalMemoryUnicodeString;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE physicalMemoryHandle = NULL;
PVOID PhysicalMemorySection = NULL;
ULONG inIoSpace, inIoSpace2;
NTSTATUS ntStatus;
PHYSICAL_ADDRESS physicalAddressBase;
PHYSICAL_ADDRESS physicalAddressEnd;
PHYSICAL_ADDRESS viewBase;
PHYSICAL_ADDRESS mappedLength;
BOOLEAN translateBaseAddress;
BOOLEAN translateEndAddress;
PVOID virtualAddress;
if ( ( inputBufferLength < sizeof (PHYSICAL_MEMORY_INFO) ) ||
( outputBufferLength < sizeof (PVOID) ) )
{
MapMemDebugPrint(("MapMem: Insufficient input or output buffer\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
interfaceType = ppmi->interfaceType;
busNumber = ppmi->busNumber;
physicalAddress = ppmi->physicalAddress;
length = ppmi->length;
//
// Get a pointer to physical memory...
//
// - Create the name
// - Initialize the data to find the object
// - Open a handle to the oject and check the status
// - Get a pointer to the object
// - Free the handle
//
RtlInitUnicodeString(&physicalMemoryUnicodeString,
L"\\Device\\PhysicalMemory");
InitializeObjectAttributes (&objectAttributes,
&physicalMemoryUnicodeString,
OBJ_CASE_INSENSITIVE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL);
ntStatus = ZwOpenSection (&physicalMemoryHandle,
SECTION_ALL_ACCESS,
&objectAttributes);
if (!NT_SUCCESS(ntStatus))
{
MapMemDebugPrint(("MapMem: ZwOpenSection failed\n"));
goto done;
}
ntStatus = ObReferenceObjectByHandle (physicalMemoryHandle,
SECTION_ALL_ACCESS,
(POBJECT_TYPE) NULL,
KernelMode,
&PhysicalMemorySection,
(POBJECT_HANDLE_INFORMATION) NULL);
if (!NT_SUCCESS(ntStatus))
{
MapMemDebugPrint(("MapMem: ObReferenceObjectByHandle failed\n"));
goto close_handle;
}
//
// Have a second variable used for the second HalTranslateBusAddres call.
//
inIoSpace = inIoSpace2 = 0;
//
// Initialize the physical addresses that will be translated
//
physicalAddressEnd = RtlLargeIntegerAdd (physicalAddress,
RtlConvertUlongToLargeInteger(
length));
//
// Translate the physical addresses.
//
translateBaseAddress =
HalTranslateBusAddress (interfaceType,
busNumber,
physicalAddress,
&inIoSpace,
&physicalAddressBase);
translateEndAddress =
HalTranslateBusAddress (interfaceType,
busNumber,
physicalAddressEnd,
&inIoSpace2,
&physicalAddressEnd);
if ( !(translateBaseAddress && translateEndAddress) )
{
MapMemDebugPrint(("MapMem: HalTranslateBusAddress failed\n"));
ntStatus = STATUS_UNSUCCESSFUL;
goto close_handle;
}
//
// Calculate the length of the memory to be mapped
//
mappedLength = RtlLargeIntegerSubtract (physicalAddressEnd,
physicalAddressBase);
//
// If the mappedlength is zero, somthing very weird happened in the HAL
// since the Length was checked against zero.
//
if (mappedLength.LowPart == 0)
{
MapMemDebugPrint(("MapMem: mappedLength.LowPart == 0\n"));
ntStatus = STATUS_UNSUCCESSFUL;
goto close_handle;
}
length = mappedLength.LowPart;
//
// If the address is in io space, just return the address, otherwise
// go through the mapping mechanism
//
if (inIoSpace)
{
*((PVOID *) ioBuffer) = physicalAddressBase.LowPart;
}
else
{
//
// initialize view base that will receive the physical mapped
// address after the MapViewOfSection call.
//
viewBase = physicalAddressBase;
//
// Let ZwMapViewOfSection pick an address
//
virtualAddress = NULL;
//
// Map the section
//
ntStatus = ZwMapViewOfSection (physicalMemoryHandle,
(HANDLE) -1,
&virtualAddress,
0L,
length,
&viewBase,
&length,
ViewShare,
0,
PAGE_READWRITE | PAGE_NOCACHE);
if (!NT_SUCCESS(ntStatus))
{
MapMemDebugPrint(("MapMem: ZwMapViewOfSection failed\n"));
goto close_handle;
}
//
// Mapping the section above rounded the physical address down to the
// nearest 64 K boundary. Now return a virtual address that sits where
// we wnat by adding in the offset from the beginning of the section.
//
(ULONG) virtualAddress += (ULONG)physicalAddressBase.LowPart -
(ULONG)viewBase.LowPart;
*((PVOID *) ioBuffer) = virtualAddress;
}
ntStatus = STATUS_SUCCESS;
close_handle:
ZwClose(physicalMemoryHandle);
done:
MapMemDebugPrint(("\t ntStatus = %x\n"));
return ntStatus;
}